/*
 * Copyright 2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.gradle.buildinit.plugins.internal

import org.gradle.api.internal.file.BaseDirFileResolver
import org.gradle.api.internal.file.TestFiles
import org.gradle.test.fixtures.file.TestNameTestDirectoryProvider
import org.junit.Rule
import spock.lang.Specification

import static org.gradle.buildinit.plugins.internal.modifiers.BuildInitDsl.GROOVY
import static org.gradle.util.TextUtil.toPlatformLineSeparators
import static org.hamcrest.Matchers.containsString
import static org.hamcrest.Matchers.equalTo

class BuildScriptBuilderGroovyTest extends Specification {

    @Rule
    TestNameTestDirectoryProvider tmpDir = new TestNameTestDirectoryProvider()

    def fileResolver = new BaseDirFileResolver(TestFiles.fileSystem(), tmpDir.testDirectory, TestFiles.patternSetFactory)
    def builder = new BuildScriptBuilder(GROOVY, fileResolver, "build")

    def outputFile = tmpDir.file("build.gradle")

    def "generates basic groovy build script"() {
        when:
        builder.create().generate()

        then:
        assertOutputFile("""/*
 * This file was generated by the Gradle 'init' task.
 */
""")
    }

    def "can add groovy build script comment"() {
        when:
        builder.fileComment("""This is a sample
see more at gradle.org""")
        builder.create().generate()

        then:
        assertOutputFile("""/*
 * This file was generated by the Gradle 'init' task.
 *
 * This is a sample
 * see more at gradle.org
 */
""")
    }

    def "can add plugins to groovy build script"() {
        when:
        builder.plugin("Add support for the Java language", "java")
        builder.plugin("Add support for Java libraries", "java-library")
        builder.create().generate()

        then:
        assertOutputFile("""/*
 * This file was generated by the Gradle 'init' task.
 */

plugins {
    // Add support for the Java language
    id 'java'

    // Add support for Java libraries
    id 'java-library'
}
""")
    }

    def "can add compile dependencies to groovy build scripts"() {
        when:
        builder.compileDependency("Use slf4j", "org.slf4j:slf4j-api:2.7", "org.slf4j:slf4j-simple:2.7")
        builder.compileDependency("Use Scala to compile", "org.scala-lang:scala-library:2.10")
        builder.create().generate()

        then:
        assertOutputFile("""/*
 * This file was generated by the Gradle 'init' task.
 */

dependencies {
    // Use slf4j
    compile 'org.slf4j:slf4j-api:2.7'
    compile 'org.slf4j:slf4j-simple:2.7'

    // Use Scala to compile
    compile 'org.scala-lang:scala-library:2.10'
}

// In this section you declare where to find the dependencies of your project
repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}
""")
    }

    def "can add test compile and runtime dependencies to groovy build scripts"() {
        when:
        builder.testCompileDependency("use some test kit", "org:test:1.2", "org:test-utils:1.2")
        builder.testRuntimeDependency("needs some libraries at runtime", "org:test-runtime:1.2")
        builder.create().generate()

        then:
        assertOutputFile("""/*
 * This file was generated by the Gradle 'init' task.
 */

dependencies {
    // use some test kit
    testCompile 'org:test:1.2'
    testCompile 'org:test-utils:1.2'

    // needs some libraries at runtime
    testRuntime 'org:test-runtime:1.2'
}

// In this section you declare where to find the dependencies of your project
repositories {
    // Use jcenter for resolving your dependencies.
    // You can declare any Maven/Ivy/file repository here.
    jcenter()
}
""")
    }

    def "can add further configuration"() {
        given:
        builder
            .taskPropertyAssignment(null, "test", "Test", "maxParallelForks", 23)
            .propertyAssignment(null, "foo.bar", "bazar")
            .conventionPropertyAssignment("Convention configuration A", "application", "mainClassName", "com.example.Main")
            .conventionPropertyAssignment("Convention configuration B", "application", "applicationName", "My Application")
            .conventionPropertyAssignment("C convention", "c", "cp", 42)
            .conventionPropertyAssignment("B convention", "b", "bp", 0)
            .taskMethodInvocation("Use TestNG", "test", "Test", "useTestNG")
            .propertyAssignment(null, "cathedral", 42)
            .taskPropertyAssignment("Disable tests", "test", "Test", "enabled", false)

        when:
        builder.create().generate()

        then:
        assertOutputFileContains("""
            foo.bar = 'bazar'

            cathedral = 42
            
            // Convention configuration A
            mainClassName = 'com.example.Main'

            // Convention configuration B
            applicationName = 'My Application'

            // B convention
            bp = 0

            // C convention
            cp = 42

            test {

                maxParallelForks = 23

                // Use TestNG
                useTestNG()

                // Disable tests
                enabled = false
            }
        """)
    }

    def assertOutputFileContains(String substring) {
        assert outputFile.file
        outputFile.assertContents(
            containsString(toPlatformLineSeparators(substring.stripIndent().trim())))
    }

    def assertOutputFile(String contents) {
        assert outputFile.file
        outputFile.assertContents(equalTo(toPlatformLineSeparators(contents)))
    }

}
